/**
 * Clase encargada de coordinar a los spiders para que ejecuten los trabajos.
 * 
 * @author HPCIII_Team2013
 */
package cl.ucn.hpc.webCrawler;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import cl.ucn.hpc.direccion.Direction;
import cl.ucn.hpc.webCrawler.ConcreteQueue;
import cl.ucn.hpc.webCrawler.IQueue;
import cl.ucn.hpc.webCrawler.Trabajo;

public class PoolSpider implements Runnable{
	private String path;
	private int consultarNumSpiders;
	private Direction d;
	private int cantMaxSpiders;
	
	/**
	 * Constructor de la clase.
	 * 
	 * @param pathRec Directorio general donde debe almacenar la informacion recibida.
	 */
	public PoolSpider(String pathRec){
		path = pathRec;		
		d = Direction.getInstance();
		cantMaxSpiders = 20;
		consultarNumSpiders = 10;
	}
	
	/**
	 * Determina la cantidad de spiders que debiesen estar trabajando sobre la lista de trabajos.
	 * Se asume que en promedio cada spider se demora medio segundo en procesar una pagina.
	 * De esta forma, se determina la cantidad necesaria para procesar todos los trabajos pendientes en un segundo.
	 * Esto sin exceder la maximo de spiders propuesto.
	 * 
	 * @return La cantidad calculada.
	 */
	private int calcularSpidersNecesarios(LinkedBlockingQueue<String> linksPendientes) {
		int tamLista = linksPendientes.size();
		int cantSpiders = tamLista/2;
		
		if(cantSpiders <= cantMaxSpiders){
			return cantSpiders;
		}else{
			return cantMaxSpiders;
		}
	}

	/**
	 * Obtiene un listado con las nuevas paginas encontradas.
	 * y las envia a la clase que almacena las direcciones.
	 * 
	 * @param linksEncontrados Listado con las nuevas url.
	 */
	public void addLinks(List<String> linksEncontrados) {		
		if(linksEncontrados != null){
			for(String i : linksEncontrados){
				d.agregarLinkNuevo(i);
			}	
		}			
	}

	/**
	 * Obtiene un link de la lista entregada. Si esta vacia, espera a que se le ingrese un dato.
	 * 
	 * @param lista Lista desde la que se debe sacar un link.
	 * @return El link obtenido.
	 */
	private String takeLink(LinkedBlockingQueue<String> lista){
		String l = null;
		while (l == null) {
			try {
				l = lista.take();
			} catch (InterruptedException e) {
				
			}
		}
		
		return l;
	}
	
	/**
	 * Coordina el trabajo de los spiders.
	 * Les asigna las paginas sobre las que deben trabajar, y obtiene los nuevos enlaces encontrados.
	 * Cada cierto numero de paginas revisadas, pregunta si hay que crear mas spiders.
	 * 
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
		int cantSpiders;
		int contIteraciones = 0;		
		LinkedBlockingQueue<String> linksPendientes = d.getLinksPendientes();
		IQueue cola = new ConcreteQueue(3,this);
					
		while(true){
			String url = takeLink(linksPendientes);
			Trabajo trab = new Trabajo(path,url);
			
			boolean ingreso = cola.put(trab);
			while (ingreso == false){
				ingreso = cola.put(trab);
			}
						
			contIteraciones++;
			
			if(contIteraciones == consultarNumSpiders){				
				cantSpiders= calcularSpidersNecesarios(linksPendientes);
				cola.setCantTrabajadores(cantSpiders);
				
				contIteraciones = 0;
			}
		}
	}
}
